package map
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.display.Sprite;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.utils.Dictionary;
	
	import loader.core.LoadType;
	
	import manager.CharManager;
	import manager.LoadManager;
	
	import ui.scene.MainScene;
	
	import utils.DisplayUtil;
	
	public class GameMap
	{
		//地图层
		public static const FRONT_LAYER:String = "frontLayer";// 前景
		public static const ITEM_LAYER:String = "itemLayer";
		public static const ACTOR_LAYER:String = "actorLayer";
		public static const GROUND_LAYER:String = "groundLayer";// 地面(近景)
		public static const VISTA_LAYER:String = "vistaLayer";// 远景(中景)
		public static const BACK_LAYER:String = "backLayer";// 背景（远景）
		
		private var mapPath:String = LoadManager.resourcePath + "testRes/map/";
		
		private var _smallMap:Bitmap;// 小地图，用来做初始加载马赛克
		public function get smallMap():Bitmap { return this._smallMap; }
		public function set smallMap(vaule:Bitmap):void{
			this._smallMap = vaule;
			if(_smallMap != null && _smallMap.bitmapData != null){
				ratioX = _smallMap.bitmapData.width/MapInfo.width;
				ratioY = _smallMap.bitmapData.height/MapInfo.height;
			}
		}
		
		private var ratioX:Number;// 小地图相对于完整地图横向缩放比例
		private var ratioY:Number;// 小地图相对于完整地图纵向缩放比例
		
		//马赛克偏移
		private var _matrixMask:Matrix=new Matrix();
		//世界层偏移
		private var _matrixWorld:Matrix  = new Matrix();
		
		private var initX:int = 0;//整个地面层默认的坐标
		private var initY:int = 0;
		
		public static var allMapImgData:Array = [];// 当前地图用到的所有图片数据
		public static var allMapImgPos:Array = [];// 当前地图用到的所有图片数据
		private var usedMap:Dictionary;//储存地图使用状态
		
		public var _mainScene:MainScene;
		
		public static var layerDeepIndex:Array = [];
		public static var layerChildCount:Array = [];
		
		public function GameMap(scene:MainScene)
		{
			super();
			
			_mainScene = scene;
			
			initLayer();
			
			usedMap = new Dictionary();
		}
		
		public function initLayer():void{
			// 层深度序号
			layerDeepIndex[BACK_LAYER] = 0;
			layerDeepIndex[VISTA_LAYER] = 1;
			layerDeepIndex[GROUND_LAYER] = 2;
			layerDeepIndex[ACTOR_LAYER] = 3;
			layerDeepIndex[ITEM_LAYER] = 4;
			layerDeepIndex[FRONT_LAYER] = 5;
			
			// 初始化地图各层深度起始Index
			resetLayerChildCount();
		}
		
		public function resetLayerChildCount():void{
			layerChildCount[layerDeepIndex[BACK_LAYER]] = 0;
			layerChildCount[layerDeepIndex[VISTA_LAYER]] = 0;
			layerChildCount[layerDeepIndex[GROUND_LAYER]] = 0;
			layerChildCount[layerDeepIndex[ACTOR_LAYER]] = 0;
			layerChildCount[layerDeepIndex[ITEM_LAYER]] = 0;
			layerChildCount[layerDeepIndex[FRONT_LAYER]] = 0;
		}
		
		// 向指定层添加显示对象
		public function addLayerChild(child:DisplayObject, layerType:String):void{
			/*if(GROUND_LAYER == layerType && layerChildCount[layerDeepIndex[GROUND_LAYER]] > 3)
				return;*/
			
			var index:int = 0;
			
			for each(var deepIndex:int in layerDeepIndex){
				if(deepIndex < layerDeepIndex[layerType]){
					index += layerChildCount[deepIndex];
				}
			}
			
			if(!_mainScene.contains(child))
			{
				layerChildCount[layerDeepIndex[layerType]]++;
			}
			
			if(index > _mainScene.numChildren)
			{
				trace("numChildren:" + _mainScene.numChildren + "----index:"+index)
			}
			else// if(last_z_index != index)
			{
				_mainScene.addChildAt(child, index);
			}
			
			return;
		}
		
		// 从至顶层删除显示对象
		public function removeLayerChild(child:DisplayObject, layerType:String):void{
			if(_mainScene!=null){
				if(child!=null && _mainScene.contains(child)){
					_mainScene.removeChild(child);
					
					layerChildCount[layerDeepIndex[layerType]]--;
				}
			}
		}
		
		//根据xml初始层的数据，加载层的相关图
		public function initMap(mapInfo:XML):void{
			if(mapInfo == null)
				return;
			
			var mapImg:MapImgInfo;
			var item:XML;
			for each(var layer:XML in mapInfo.children()){
				if(layer.@name == GROUND_LAYER){
					//地面会运动，有初始的坐标
					//保证加载上来xml后，地面层初始的的偏移是正确的，否则只有调用了setOffset才会更新初始的偏移
					initX = layer.@x
					initY = layer.@y;
					for each(item in layer.children()){
						var buildKey:String = item.@name;
						var buildPoint:Point = new Point(item.@x, item.@y);
						
						allMapBuildPos[buildKey] = buildPoint;
						allMapBuildKey[buildKey] = buildKey;
						
						mapImg = new MapImgInfo();
						mapImg.layerType = FRONT_LAYER;
						mapImg.x = item.@x;
						mapImg.y = item.@y;
						mapImg.key = buildKey;
						mapImg.loadType = LoadType.LOAD_IMG;
						mapImg.path = mapPath +MapInfo.resId+"/"+buildKey;
						
						//LoadManager.loadedImg(mapPath +MapInfo.resId+"/"+buildKey);
					}
				}
				else{
					for each(item in layer.children()){
						mapImg = new MapImgInfo();
						mapImg.layerType = layer.@name;
						mapImg.x = item.@x;
						mapImg.y = item.@y;
						mapImg.loadType = LoadType.LOAD_MAP_TILE;
						//-----------------加载图-------------------
						//公用的素材 ,前景   todo：如果同一张地图上用相同的item处理？？
						if(layer.@name == ITEM_LAYER || layer.@name == FRONT_LAYER){
							var itemName:String = item.@name;
							itemName = "Map_"+itemName.substr(0,itemName.lastIndexOf("."));
							mapImg.path = mapPath + "item/"+itemName+".swf";
							mapImg.key =  itemName;
							//某层是否需要横向平铺
							if(item.@repeat == "true"){
								mapImg.repeat = true;
							}
						}else{//背景 远景
							mapImg.path = mapPath +MapInfo.resId+"/swf/map.swf";//地图编号所在的文件夹
							mapImg.key = MapInfo.resId + "|" + item.@name;
						}
						loadMapImg(mapImg);
					}
				}
			}
			
		}
		
		//加载图
		public function loadMapImg(mapImg:MapImgInfo):void{
			// 缓存地图资源加载位置
			var mapTilePos:Point = new Point(mapImg.x,mapImg.y);
			allMapImgPos[mapImg.key] = mapTilePos;
			
			var mapTileData:BitmapData = LoadManager.loadMap(mapImg);
			var mapTile:Bitmap;
			if(null != mapTileData)
			{
				mapTile = new Bitmap(mapTileData);
			}
			else{
				//还没有加载上的地面层用马赛克替代
				if(mapImg.layerType == GROUND_LAYER && null != smallMap && smallMap.bitmapData != null){
					_matrixMask.identity();
					_matrixMask.translate(-(mapImg.x*ratioX),-(mapImg.y*ratioY));
					_matrixMask.scale(1/ratioX,1/ratioY);
					mapTileData = new BitmapData(MapInfo.map_block_w,MapInfo.map_block_h,true,0);
					mapTileData.draw(smallMap.bitmapData,_matrixMask);
				}
				else{
					mapTileData = new BitmapData(MapInfo.map_block_w,MapInfo.map_block_h,true,0);
				}
				
				mapTile = new Bitmap(mapTileData);
			}
			
			//远景 背景(整张图) //前景，地面，物品（多张图拼为一张）
			if(mapImg.layerType == VISTA_LAYER){
				addLayerChild(mapTile, VISTA_LAYER);
			}else if(mapImg.layerType == BACK_LAYER){
				addLayerChild(mapTile, BACK_LAYER);
			}else if(mapImg.layerType == FRONT_LAYER){
				addLayerChild(mapTile, FRONT_LAYER);
			}else if(mapImg.layerType == ITEM_LAYER){
				addLayerChild(mapTile, ITEM_LAYER);
			}else if(mapImg.layerType == ACTOR_LAYER){
				addLayerChild(mapTile, ACTOR_LAYER);
			}else{
				usedMap[mapImg.key] = true;
				addLayerChild(mapTile, GROUND_LAYER)
			}
			
			// 缓存地图资源
			mapTile.x = mapImg.x;
			mapTile.y = mapImg.y;
			
			allMapImgData[mapImg.key] = mapTile;
		}
		
		//移动地图所有层,及角色层
		public function setMapOffset(dx:int,dy:int):void{
			//移动角色
			CharManager.getInstance().moveAllCharacterWithOutPlayer();
			
			//加载当前可见区域的地面层
			//地面
			move(dx,dy);
			
			// 建筑
			//moveBuild(dx, dy);
		}
		
		/**
		 * 地图偏移
		 * 1. 重新计算要加载的地图范围
		 * 2. 隐藏之前加载的所有地图
		 * 3. 加载新的地图, 地图的命名规则参靠getRowOrCol(rowOrCol)
		 * @param dx 屏幕左上点相对地图原点(0, 0)的x坐标
		 * @param dy 屏幕左上点相对地图原点(0, 0)的y坐标
		 */		
		public function move(dx:int,dy:int):void{
			
			var leftX:int = dx / MapInfo.map_block_w;
			var rightX:int = leftX + MapInfo.map_cache_Cols;//横向4块
			if (rightX >= MapInfo.map_block_Cols){
				rightX = MapInfo.map_block_Cols - 1;
				leftX = rightX - MapInfo.map_cache_Cols;
			}
			
			var topY:int = dy / MapInfo.map_block_h;
			var downY:int = topY + MapInfo.map_cache_Rows;
			if (downY >= MapInfo.map_block_Rows){
				downY = MapInfo.map_block_Rows - 1;
				topY = downY - MapInfo.map_cache_Rows;
			}
			
			
			// 平移已加载图像
			hideAllTile();
			//加载当前可见区域地图块
			for (var i:int=leftX;i<=rightX;i++){
				for (var n:int=topY;n<=downY;n++){
					var key:String = "|map,"+i+"_"+n;
					var img:Bitmap = allMapImgData[key];
					
					if(i >= 0 && n >= 0 ){
						if(null == allMapImgPos[key])
						{
							allMapImgPos[key] = new Point(i*MapInfo.map_block_w, n*MapInfo.map_block_h);
						}
						
						if(img == null || (img != null && img.bitmapData == null)){
							var mapImg:MapImgInfo = new MapImgInfo();
							mapImg.layerType = GROUND_LAYER;
							mapImg.x = i*MapInfo.map_block_w;
							mapImg.y = n*MapInfo.map_block_h;
							mapImg.key = key;
							mapImg.loadType = LoadType.LOAD_MAP_TILE;
							mapImg.path = mapPath +MapInfo.resId+"/"+i+"_"+n+".jpg";
							
							loadMapImg(mapImg);
						}else{
							usedMap[key] = true;
							//保证马塞克能被加载上来的图替换
							if(LoadManager.loadedMap[key] != undefined && img.bitmapData != null){
								img.bitmapData = LoadManager.loadedMap[key];
							};
							
							img.x = allMapImgPos[key].x-dx;
							img.y = allMapImgPos[key].y-dy
							
							addLayerChild(img, GROUND_LAYER);
						}
					}
				}
			} 
		}
		
		/**
		 * 清除看不见的地图(地面层)
		 * 在加载新地图之前，将之前加载的地图移除显示列表 
		 */		
		public function hideAllTile():void{
			for(var key:Object in allMapImgData){
				if (usedMap[key] == true && allMapImgData[key] != null){
					removeLayerChild(allMapImgData[key], GROUND_LAYER);
					//DisplayUtil.remove(allMapImgData[key]);
					usedMap[key] = false;
				}
			}
			//usedMap = new Dictionary();
		}
		
		//清除地图资源 	
		public function destory():void{
			initX = initY = 0;
			allMapImgData = [];
			LoadManager.destory();
		}
		
		
		//=====建筑==========================================================
		public static var allMapBuildKey:Array = [];// 当前地图用到的所有图片数据
		public static var allMapBuildPos:Array = [];// 当前地图用到的所有图片数据
		
		private function moveBuild(dx:int,dy:int):void{
			for(var buildKey:String in allMapBuildKey)
			{
				var build:Bitmap = allMapImgData[buildKey];
				/*build.x = allMapBuildPos[buildKey].x - dx;
				build.y = allMapBuildPos[buildKey].y - dy;*/
				
				build.x = 500;
				build.y = 0;
				
				_mainScene.addChild(build);
				//addLayerChild(build, FRONT_LAYER);
			}
		}
	}
}